/**
 * Company : Thai Informatic System Co., Ltd.
 * Created By : Dr.Tree
 * Created On : Oct 25, 2011  10:27:21 AM 
 * e-Mail : chatree@tis.co.th
 * Mobile Phone : (+66) 087-921-5115
 * Package Name : tis.services.common
 * File Name : ServiceCommon.java
 * TODO
 */
package jpa.service.synchro.common;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import jpa.entitys.synchro.common.CommonEntity;
import org.apache.log4j.Logger;
import promis.utility.CommonService;
import sap.jco.server.SAPServerInfo;

/**
 * 
 * @author Chatree Siangklom of Administrator
 * Date =Nov 13, 2013 : 11:57:46 AM 
 * CreateBy=Chatree Siangklom
 * 
 * JPAService
 * TODO
 */
public class JPAService implements JPAServiceIntrerface {
	
	private static final Logger log = Logger.getLogger(JPAService.class);	
	private EntityManagerFactory emf;
	
	@PersistenceContext
	private EntityManager em;
	
	private String user = SAPServerInfo.User();
	private String password = SAPServerInfo.Password();
	private Date current_date = Calendar.getInstance().getTime();
	private String current_stringDateTime = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss").format(Calendar.getInstance().getTime());	
	private int pageSize = 0;
	
	public void setPageSize(int pageSize) {
	    this.pageSize = pageSize;
    }

    public int getPageSize() {
    	return pageSize;
    }

	/**
	 * @return the user
	 */
	public String getUser() {
		return user;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @return the current_date
	 */
	public Date getCurrent_date() {
		return current_date;
	}

	/**
	 * @return the current_stringDateTime
	 */
	public String getCurrent_stringDateTime() {
		return current_stringDateTime;
	}

	public JPAService(EntityManager em){
		this.em = em;
		/*
		if(emf == null)
			emf = Persistence.createEntityManagerFactory("MyJPAProject");
		if(em == null)
			em = emf.createEntityManager();
		*/
	} 
	
	/**
	 * @return the emf
	 */
	protected EntityManagerFactory getEmf() {
		return emf;
	}

	/**
	 * @param emf the emf to set
	 */
	public void setEmf(EntityManagerFactory emf) {
		this.emf = emf;
	}

	/**
	 * @return the em
	 */
	protected EntityManager getEm() {
		return em;
	}

	/**
	 * @param em the em to set
	 */
	public void setEm(EntityManager em) {
		this.em = em;
	}	
	
	protected <T> T ConvertToYoureObject(CommonEntity object) throws Exception {
		if(CommonService.IsNull((Object)object)) 
			return null;
		else 
			return (T)object;
	}
	
	public <T> List<T> ConvertToYoureObject(List<CommonEntity> obj_lst) throws Exception {
		if(CommonService.IsNull(obj_lst)) 
			return null;
		
		List<T> newlst = new ArrayList<T>();
		for(CommonEntity model : obj_lst) 
			newlst.add((T)model);
				
		return newlst;
	}
		
	@Override
	/**
	 * Need Name is Id
	 */
	public CommonEntity find(String id,String NamedQuery) throws Exception {
		EntityTransaction t = null;
		try {
			  
			  t = this.em.getTransaction();	        	        
		        t.begin();
		        
		        Query query = this.em.createNamedQuery(NamedQuery);	    
		        query.setParameter("Id", id);

		        List lst = query.getResultList();	        
		        t.commit();
		        
	        	if(lst != null && lst.size() > 0)
		        	return (CommonEntity)lst.get(0);
	        	
		  } finally {
			  if (t.isActive()) 
				  t.rollback();
		  }
		return null;
	}
	
	public List<CommonEntity> findByInstanceNo(String instanceNo,String NamedQuery) throws Exception {
		EntityTransaction t = null;
		try{
			
			t = this.em.getTransaction();	        	        
	        t.begin();
	        
	        Query query = this.em.createNamedQuery(NamedQuery);	    
	        query.setParameter("instanceNo", instanceNo);
	        
	        List lst = query.getResultList();
	        t.commit();
	        
	        return lst;
		}finally {
			  if (t.isActive()) 
				  t.rollback();
		}
	}
	
	public List<CommonEntity> findByInstanceNo(String instanceNo,String NamedQuery, int pageNum) throws Exception {	
		try{
	        Query query = this.em.createNamedQuery(NamedQuery);
	        
	        if(this.getPageSize() > 0){
	        	query.setFirstResult(getPageSize() * pageNum);	        
		        query.setMaxResults(getPageSize());	
	        }
	        
	        query.setParameter("instanceNo", instanceNo);
	        
	        return query.getResultList();
		}finally {
			//em.setFlushMode(FlushModeType.COMMIT);
			//System.out.println("findByInstanceNo Current DateTime=" + this.getCurrent_stringDateTime());
		}
	}
	
	@Override
	public CommonEntity find(String id) throws Exception {
		return null;
	}
	
	@Override
	public List<CommonEntity> find(String NamedQuery, Map<String, Object> mapWhereValue) throws Exception {
		EntityTransaction t = null;

		try{			
	        t = this.em.getTransaction();	        	        
	        t.begin();
	        
	        Query query = this.em.createNamedQuery(NamedQuery);
	        if(!mapWhereValue.isEmpty())
	        {
	        	Set s = mapWhereValue.entrySet();
	        	Iterator it=  s.iterator();
	        	while(it.hasNext())
    	        {	            
    	            Map.Entry m =(Map.Entry)it.next();    	            
    	            query.setParameter((String)m.getKey(), m.getValue());    	           
    	        }
	        }
	        
        	List lst = query.getResultList();
        	t.commit();
	        return lst;
		}finally {
			  if (t.isActive()) 
				  t.rollback();
		}
	}
	
	public List<CommonEntity> find(String NamedQuery, Map<String, Object> mapWhereValue, int pageNum) throws Exception {
		EntityTransaction t = null;
		try{			
	        t = this.em.getTransaction();	        	        
	        t.begin();
	        
	        Query query = this.em.createNamedQuery(NamedQuery);
	        if(!mapWhereValue.isEmpty())
	        {
	        	Set s = mapWhereValue.entrySet();
	        	Iterator it=  s.iterator();
	        	while(it.hasNext())
    	        {	            
    	            Map.Entry m =(Map.Entry)it.next();    	            
    	            query.setParameter((String)m.getKey(), m.getValue());    	           
    	        }
	        }
	        
	        if(getPageSize() > 0){
	        	query.setFirstResult(getPageSize() * pageNum);
		        query.setMaxResults(getPageSize());	
	        }
	        
        	List lst = query.getResultList();
        	t.commit();
	        return lst;
		}finally {
			  if (t.isActive()) 
				  t.rollback();
		}
	}
	
	protected List<CommonEntity> findAll(String NamedQuery) throws Exception {
		EntityTransaction t = null;
		try{					        			
			t = this.em.getTransaction();	        	        
	        t.begin();
	        
			Query query = this.em.createNamedQuery(NamedQuery);	   
	        List lst = query.getResultList();
	        t.commit();
	        
	        return (CommonService.getSize(lst) > 0) ? lst : null; 
		}
	    catch(Exception e){
	    	t.rollback();
	    	log.error(e.getMessage());
	    	throw e;
		}finally{
			if (t.isActive()) 
			  t.rollback();
			//em.setFlushMode(FlushModeType.COMMIT);
		}
	}
	
	protected List<CommonEntity> findAllMaxResult(String NamedQuery, int maxResult) throws Exception {
		EntityTransaction t = null;
		try{					        			
			t = this.em.getTransaction();	        	        
			t.begin();
			
			Query query = this.em.createNamedQuery(NamedQuery);	  
			
			if(maxResult > 0)
				query.setMaxResults(maxResult);
			
			List lst = query.getResultList();
			t.commit();
			
			return (CommonService.getSize(lst) > 0) ? lst : null; 
		}
		catch(Exception e){
			t.rollback();
			log.error(e.getMessage());
			throw e;
		}finally{
			if (t.isActive()) 
				t.rollback();
			//em.setFlushMode(FlushModeType.COMMIT);
		}
	}
	
	protected List<CommonEntity> findAll(String NamedQuery, int pageNum) throws Exception {
		EntityTransaction t = null;
		try{
			t = this.em.getTransaction();	        	        
	        t.begin();
	        
	        Query query = this.em.createNamedQuery(NamedQuery);
	        //query.setLockMode(LockModeType.NONE);
	        
	        if(this.getPageSize() > 0){
	        	query.setFirstResult(this.getPageSize() * pageNum);
		        query.setMaxResults(this.getPageSize());	
	        }	       
	        
	        List lst = query.getResultList();
	        t.commit();
	        
	        return (CommonService.getSize(lst) > 0) ? lst : null;
	       
		}
	    catch(Exception e){
	    	t.rollback();
	    	log.error(e.getMessage());
	    	throw e;
		}finally{
			if (t.isActive()) 
			  t.rollback();
			//em.setFlushMode(FlushModeType.COMMIT);
		}
	}
	
	protected List<CommonEntity> findAll(String NamedQuery, int pageSize, int pageNum) throws Exception {
		EntityTransaction t = null;
		try{
			t = this.em.getTransaction();	        	        
	        t.begin();
	        
	        Query query = this.em.createNamedQuery(NamedQuery);
	        //query.setLockMode(LockModeType.NONE);
	        
	        if(this.getPageSize() > 0){
	        	query.setFirstResult(pageSize * pageNum);
		        query.setMaxResults(pageSize);	
	        }	       
	        
	        List lst = query.getResultList();
	        t.commit();
	        
	        return (CommonService.getSize(lst) > 0) ? lst : null;
	       
		}
	    catch(Exception e){
	    	t.rollback();
	    	log.error(e.getMessage());
	    	throw e;
		}finally{
			if (t.isActive()) 
			  t.rollback();
		}
	}
	
	protected CommonEntity findMax(String NamedQuery) throws Exception {
		EntityTransaction t = null;
		try{			
			t = this.em.getTransaction();	        	        
	        t.begin();
	        
			Query query = this.em.createNamedQuery(NamedQuery);
			//query.setLockMode(LockModeType.NONE);
			List<CommonEntity> lst = query.getResultList();
			
			t.commit();
			
			return (CommonService.getSize(lst) == 1) ? lst.get(0) : null;
		}catch(Exception e){			
			log.error(e.getMessage());
			t.rollback();
			e.printStackTrace();
		}finally{
			if (t.isActive()) 
				  t.rollback();
			//em.setFlushMode(FlushModeType.COMMIT);		
		}
		return null;
	}
	

	/**
	 * 
	 * @param company_name is case sensitive
	 * @param sequence_name is case sensitive
	 * @return
	 */
	protected synchronized String SequenceNext(String sequence_name) throws Exception {
		EntityTransaction t = null;
		try{
			
			t = this.em.getTransaction();
	        t.begin();
        	Query query = em.createNativeQuery("SELECT GETFN_SYNC_SEQUENCE(?1) FROM DUAL");        
        	//query.setLockMode(LockModeType.NONE);
        	
        	query.setParameter(1, sequence_name);
        	String current_next = (String)query.getSingleResult();	
        	
        	t.commit();
        	
        	return current_next;
        	
		}finally{
			if (t.isActive()) 
				  t.rollback();
		}
	}
	
	public synchronized String GetNewInstanceNo() throws Exception {
		return SequenceNext("INSTANCE");
	}
	
	protected void autoAsignDefaultValues(CommonEntity object)  throws Exception
	{
		try{
			
	        
		}catch(Exception e)
		{
			throw e;
		}finally{
			//System.out.println("Current DateTime=" + this.getCurrent_stringDateTime());
		}
		
        return;
	}

	@Override
	public CommonEntity inserted(CommonEntity object) throws Exception {
		EntityTransaction t = null;
		try{			
	        t = this.em.getTransaction();
	        t.begin();
	        
	        em.persist(object);
	        
	        t.commit();
	        
	        return object;
		}finally{
			if (t.isActive()) 
				  t.rollback();
		}
	}
	
	@Override
	public List<CommonEntity> inserted(List<CommonEntity> object_lst) throws Exception{
		EntityTransaction t = null;
		
		try{			
	        t = this.em.getTransaction();	        	        
	        t.begin();
	        
	        List<CommonEntity> object_lst1 = new ArrayList<CommonEntity>();
	        
	        for(CommonEntity obj : object_lst){
	        	em.persist(obj); 
	        	//log.info(" inserted ==>  InstanceNo = " + obj.getInstanceNo() + ",  PromisStagingId = " + obj.getPromisStagingId());
	        	object_lst1.add(obj);
	        }
	        
	        t.commit();
	        
	        return object_lst1;
		}finally{
			if (t.isActive()) 
				  t.rollback();
		}
		 
	}
	

	@Override
	public CommonEntity updated(CommonEntity object)throws Exception {
		// TODO Auto-generated method stub
		EntityTransaction t = null;
		
		try{			
	        t = this.em.getTransaction();
	        t.begin();
	        
	        em.merge(object);
	        
	        t.commit();
	        
	        return object;
		}finally{
			if (t.isActive())
				  t.rollback();
		}
	}
	
	@Override
	public List<CommonEntity> updated(List<CommonEntity> object_lst) throws Exception{
		EntityTransaction t = null;
		
		try{			
	        t = this.em.getTransaction();
	        t.begin();
	        
	        for(CommonEntity object : object_lst)
	        	em.merge(object);
	        
	       t.commit();
	        		
	       return object_lst;
	       
		}catch(Exception e){			
			t.rollback();
	    	System.err.println(e.getMessage());
	    	log.error(e.getMessage());	    	
	    	throw e;
	    }
	    finally{
			if (t.isActive()) 
				  t.rollback();
		}
	}


	@Override
	public CommonEntity deleted(CommonEntity object)throws Exception {
		return updated(object);
	}
	
	@Override
	public List<CommonEntity> deleted(List<CommonEntity> object_lst) throws Exception
	{
		return updated(object_lst);
	}


	@Override
	public void destroyed(CommonEntity object) throws Exception{
		EntityTransaction t = null;
		try{			
	        t = this.em.getTransaction();
	        t.begin();
	        
	        em.remove(object);

	        t.commit();
		}finally{
			if (t.isActive()) 
				  t.rollback();
		}
	}
	
	@Override
	public void destroyed(List<CommonEntity> object_lst) throws Exception {
		EntityTransaction t = null;
		
		try{			
	        t = this.em.getTransaction();
	        t.begin();
	        for(CommonEntity object : object_lst)
	        	em.remove(object);
	        		
	        t.commit();
		}finally{
			if (t.isActive()) 
				  t.rollback();
		}
	}

	@Override
	public List<Object[]> findsql(String sql) throws Exception {
		try{					        
	        
	        Query query = this.em.createNativeQuery(sql);
	        return (List<Object[]>)query.getResultList();
		}finally{
			//em.setFlushMode(FlushModeType.COMMIT);
			//System.out.println("findsql ---> Current DateTime=" + this.getCurrent_stringDateTime());
		}
	}
	
	/**
	 * 
	 * @param sql
	 * @param pageSize
	 * @param pageNum
	 * @return
	 * @throws Exception
	 */
	public List<Object[]> findSql(String sql, int pageSize, int pageNum) throws Exception {
		try{
			
			 javax.persistence.Query query = getEm().createNativeQuery(sql);
			 
			 if(pageSize > 0){
				 query.setFirstResult(pageSize * pageNum);
				 query.setMaxResults(pageSize);				 
			 }
			
			//return (List<Object[]>)getEm().createNativeQuery(sql).getResultList();
			 
			 return ((List<Object[]>)query.getResultList());
								 
		}catch(Exception e){
			System.out.println(e.getMessage());
			log.error(e.getMessage());
			throw e;
		}
	}
	
	/**
	 * 
	 * @param sql
	 * @param pageSize if = 0 not use
	 * @param pageNum 
	 * @return
	 * @throws Exception
	 */
	public List findHSql(String sql, int pageSize, int pageNum) throws Exception {
		try{
			
			javax.persistence.Query query = getEm().createQuery(sql);
			
			 if(pageSize > 0){
				 query.setFirstResult(pageSize * pageNum);
				 query.setMaxResults(pageSize);				 
			 }
			 
			//return getEm().createQuery(sql).getResultList();
			 return query.getResultList();
			 
		}catch(Exception e){
			System.out.println(e.getMessage());
			log.error(e.getMessage());
			throw e;
		}
	}	
	
}
